/** 
 *  @file       ds18b20.c
 *  @brief      lcd1602显示ds18b20温度值
 *  @author     Z B T  
 *  @version    
 *  @date       2015-10 
 */

/* Includes ------------------------------------------------------------------*/
#include "lcd1602.h"
#include "DS18B20.h"
#include "delay.h"

/* Private variables ---------------------------------------------------------*/

/* Private function prototypes ------------------------------------------------*/
static void DS18B20_write_byte(unsigned char write_byte);
static unsigned char DS18B20_read_byte(void);
static unsigned char DS18B20_init(void);
static void DS18B20_start_convert(void);
static void DS18B20_read_temperature(void);

/* Public functions ---------------------------------------------------------*/

/**
 *  @brief  得到读取的温度值
 *  @param  None
 *  @return None
 */
signed int DS18B20_get_temperature(void)
{
	signed int  temp;
	unsigned char low_byte_value;
	unsigned char high_byte_value;
    
	DS18B20_start_convert();                                /**< 开始转换 */
    delay_ms(500);                                           /**< 延时大于500ms以完成温度转换 */
    DS18B20_read_temperature();                              /**< 读取温度 */
	low_byte_value  = DS18B20_read_byte();                   /**< 先读取低字节 低8位 */
	high_byte_value = DS18B20_read_byte();                   /**< 再读取高字节 高字节的低四位为数值为 高四位为符号位 */
    /** 温度数据格式 4符号位 4高位数据位 8低位数据位 */    
    if (high_byte_value & 0xf0)                             /**< 温度值小于0 */
	{
		temp = ((~high_byte_value) << 8) | (~low_byte_value + 1);
        temp |= 0xf000;                     
	}
	else        /**< 温度值大于0 */
	{
		temp = ((high_byte_value << 8) | low_byte_value);
	}
	temp = (temp >> 4) ;                                     /**< 得到真实温度值 */            

	return temp;
}
/* Private functions ---------------------------------------------------------*/

/**
 *  @brief  ds18b20初始化函数
 *  @param  None
 *  @return None
 */
static unsigned char DS18B20_init(void)
{
    unsigned char i;

    DS18B20_PIN = 1;
    delay_us(1);
    DS18B20_PIN = 0;
    /**delay 480 - 960us */
    delay_us(70);
    DS18B20_PIN = 1;
    /**< delay 15- 60 us */
    delay_us(3);

    for (i = 0; i < 24; i++)
    {
    	/** 如果总线被拉低 则初始化成功 */
    	if (DS18B20_PIN == 0)
    	{
    		/**< delay >480 us */
			delay_us(50);
			return OK;
    	}
    	delay_us(1);				/**< 每隔10us左右检测一次存在和复位脉冲信号 */
    }
    return ERROR;
}

/**
 *  @brief  ds18b20写一个字节
 *  @param  write_byte
 *  @return None
 */
static void DS18B20_write_byte(unsigned char write_byte)
{
	unsigned char i;
    unsigned char j = 0;

	for (i = 0; i < 8; i++)
	{
		DS18B20_PIN = 1;					/**< 产生总线下降沿 */
		delay_us(2);
		DS18B20_PIN = 0;
		j++;						        /**< 延时>1us */
		DS18B20_PIN = write_byte & 0x01;	/**< 写数据到总线 从最低位开始 */		
		delay_us(12);						/**< 写一位数据需要 >61us */
        DS18B20_PIN = 1;                    /**< 释放总线至少1us恢复时间后再写入第二个数据 */
		write_byte >>= 1;
	}
}

/**
 *  @brief  ds18b20读一个字节
 *  @param  write_byte
 *  @return read_byte
 */
static unsigned char DS18B20_read_byte(void)
{
	unsigned char i;
    unsigned char j = 0;
	unsigned char read_byte = 0;

	for (i = 0; i < 8; i++)
	{
		DS18B20_PIN = 0;		/**< 拉低总线 */
		j++;			        /**< 延时 >1us */
		DS18B20_PIN = 1;
		j++;			        
        j++;                    /**< 三个i++ 总延时小于15us */
		read_byte >>= 1;
		if (DS18B20_PIN == 1)	/**< 若总线处于高电平 则读取数据 */
		{
			read_byte |= 0x80;
		}
		delay_us(12);			/**< 读取一位数据时间 > 61us */
	}
	return read_byte;
}

/**
 *  @brief  开始转换温度
 *  @param  None
 *  @return None
 */
static void DS18B20_start_convert(void)
{
	DS18B20_init();
    delay_ms(1);
	DS18B20_write_byte(SKIP_READ_ROM);	/**< 单个DS18B20 故跳过读序号 */
	DS18B20_write_byte(CONVERT_T);		/**< 开始转换温度 */
}

/**
 *  @brief  开始读取转换后的温度值
 *  @param  None
 *  @return None
 */
static void DS18B20_read_temperature(void)
{
    DS18B20_init();
    delay_ms(1);
	DS18B20_write_byte(SKIP_READ_ROM);	    /**< 单个DS18B20 故跳过读序号 */
    DS18B20_write_byte(READ_SCRATCHPAD);    /**< 读取温度 */
}

